package com.cd.university.service.impl;

import com.cd.university.common.RestResult;
import com.cd.university.common.UniversityConstants;
import com.cd.university.common.obs.ObsUtils;
import com.cd.university.common.utils.MyIdGenerator;
import com.cd.university.common.utils.SpringUtil;
import com.cd.university.controller.form.*;
import com.cd.university.db.mapper.InvitationCodeMapper;
import com.cd.university.db.mapper.UserImageMapper;
import com.cd.university.db.mapper.UserMapper;
import com.cd.university.db.pojo.InvitationCode;
import com.cd.university.db.pojo.User;
import com.cd.university.db.pojo.UserImage;
import com.cd.university.service.UserService;
import com.cd.university.vo.UserVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;


/**
 * 用户业务的实现类
 * @author 陈栋
 * @create 2021/9/5 20:40
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private ObsUtils obsUtils;

    @Autowired
    private UserImageMapper userImageMapper;

    @Autowired
    private InvitationCodeMapper invitationCodeMapper;

    @Override
    public User searchUserByUserInfo(String info) {
        return userMapper.searchUserByUserInfo(info);
    }


    @Override
    public RestResult registerUser(UserRegisterForm form) {
        User registerUser = new User();
        if (form.getRoleId()==null) {
            form.setRoleId(UniversityConstants.DEFAULT_ROLE_ID);
        }
        registerUser.setUserStatus(UniversityConstants.NEW_USER_STATUS);

        // 密码加密
        form.setPassword(passwordEncoder.encode(form.getPassword()));

        BeanUtils.copyProperties(form, registerUser);

        try {
            // 插入用户
            userMapper.insert(registerUser);
            // 为新用户使用默认的头像
            userImageMapper.insertUserImage(new UserImage(registerUser.getUserId(), UniversityConstants.DEFAULT_USER_IMAGE));
            return RestResult.success("注册用户成功")
                    .put("username",form.getUsername());
        }catch (Exception exception) {
            exception.printStackTrace();
            // TODO: 2021/9/17 这里应该得到是哪个字段重复了
            return RestResult.failure("注册用户失败,用户重复");
        }
    }

    @Override
    public List<UserVo> searchAllUser() {
        return userMapper.searchAllUser();
    }

    @Override
    public int updateUserRole(Integer userId, Integer roleId) {
        User user = new User();
        user.setUserId(userId);
        user.setRoleId(roleId);

        return userMapper.updateByPrimaryKeySelective(user);
    }

    @Override
    public int deleteUserByUserId(Integer userId) {
        User user = new User();
        user.setUserStatus(UniversityConstants.NOT_AVAILABLE_STATUS);
        user.setUserId(userId);

        return userMapper.updateByPrimaryKeySelective(user);
    }

    @Override
    public int updateUserInfo(UserForm form) {
        User user = new User();

        BeanUtils.copyProperties(form, user);

        return userMapper.updateByPrimaryKeySelective(user);
    }

    @Override
    public RestResult updateUserImage(MultipartFile image) {

        if (!checkIsImage(image)) {
            return RestResult.failure("文件不是头像，请重新上传");
        }

        User user = userMapper.searchUserByUserInfo(SecurityContextHolder.getContext().getAuthentication().getName());


        Integer userId = user.getUserId();
        String filename = image.getOriginalFilename();

        // 使用用户的用户id-文件名作为上传文件名
        String objectKey = new StringBuilder()
                .append(user.getUserId()+"-")
                .append(filename).toString();

        // 更新用户的头像
        userImageMapper.updateByPrimaryKeySelective(new UserImage(userId,objectKey));

        // 上传文件
        boolean uploadFile = obsUtils.uploadFile(image, objectKey, UniversityConstants.USER_IMAGE_FOLDER);

        if (uploadFile) {
            return RestResult.success("上传文件成功");
        }else {
            return RestResult.failure("上传文件失败");
        }
    }

    @Override
    public RestResult searchUserByUserNumber(String userNumber) {
        if (StringUtils.isEmpty(userNumber)) {
            return RestResult.failure("用户编号不能为空");
        }

        User user = userMapper.searchUserByUserNumber(userNumber);

        if (user==null) {
            return RestResult.failure("用户不存在，请重新输入用户编号");
        }

        // 将user封装成userVo返回给前端
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(user,userVo);

        return RestResult.success("用户信息")
                .put("data",userVo);
    }

    @Override
    public RestResult getUserImage(HttpServletResponse response, HttpServletRequest request, Integer userId) {

        UserImage userImage = userImageMapper.selectByPrimaryKey(userId);

        if (userImage==null) {
            return RestResult.failure("用户不存在");
        }

//        boolean downloadFile = obsUtils.downloadFile(getFileName(userId), UniversityConstants.USER_IMAGE_FOLDER, response);
        String fileUrl = obsUtils.getFileUrl(getFileName(userId), UniversityConstants.USER_IMAGE_FOLDER);
        if (fileUrl!=null) {
            return RestResult.success("获取用户头像成功")
                    .put("data",fileUrl);
        }else {
            return RestResult.failure("获取文件头像失败");
        }
    }

    @Override
    public RestResult updateBasicInfo(UserBasicInfoForm form) {
        User user = new User();
        BeanUtils.copyProperties(form,user);
        int row = userMapper.updateByPrimaryKeySelective(user);

        if (row < 1) {
            return RestResult.failure(form.getUsername() + "用户基本信息更新失败");
        }

        return RestResult.success("用户更新成功")
                .put("data",form);
    }

    @Override
    public RestResult updatePwd(UserPasswordForm form) {
        User oldUser = userMapper.searchUserByUserInfo(form.getMobile());
        if (oldUser==null) {
            return RestResult.failure("该用户不存在，请注册");
        }

        String findUserPassword = oldUser.getPassword();
        // 判断密码相等是用用户输入的明文密码，和数据库中加密的密码进行匹配
        if (!passwordEncoder.matches(form.getOriginalPassword(),findUserPassword)) {
            return RestResult.failure("密码修改错误，原始密码不匹配，请重新输入");
        }
        User newUser = new User();
        newUser.setUserId(oldUser.getUserId());
        newUser.setPassword(passwordEncoder.encode(form.getNewPassword()));

        int row = userMapper.updateByPrimaryKeySelective(newUser);

        if (row < 1) {
            return RestResult.failure("密码修改失败，请重试");
        }
        return RestResult.success("密码修改成功");
    }

    @Override
    public RestResult userRetrievePassword(UserRetrievePwdBySmsForm form) {
        User oldUser = userMapper.searchUserByUserInfo(form.getMobile());

        if (oldUser==null) {
            return RestResult.failure("用户不存在，请确认电话是否正确");
        }

        User newUser = new User();
        newUser.setUserId(oldUser.getUserId());
        newUser.setPassword(passwordEncoder.encode(form.getNewPassword()));

        int row = userMapper.updateByPrimaryKeySelective(newUser);

        if (row < 1) {
            return RestResult.failure("修改密码失败");
        }

        return RestResult.success("修改密码成功");
    }

    @Override
    public RestResult confirmNewUser(Integer userId) {
        User user = new User();
        user.setUserId(userId);
        user.setUserStatus(UniversityConstants.AVAILABLE_STATUS);

        int row = userMapper.updateByPrimaryKeySelective(user);

        if (row < 1) {
            return RestResult.failure("确认用户查看新手引导视频失败");
        }
        return RestResult.success("确认用户查看新手引导视频成功");
    }


    @Override
    public RestResult GenerateSuperInvitationCode(Integer userId) {
        // 判断用户是否是超级管理员
        User user = userMapper.selectByPrimaryKey(userId);
        if (user==null || !user.getRoleId().equals(UniversityConstants.ADMIN_ROLE_ID)) {
            return RestResult.failure("该用户不存在，或者不是超级管理员");
        }

        String code = MyIdGenerator.getInstance().getRandomNumber();

        // 异步执行插入数据库操作
        UserServiceImpl bean = SpringUtil.getBean(UserServiceImpl.class);
        bean.insertInvitationCodeDb(userId, code);

        return RestResult.success(user.getUserRealname() + "：生成的邀请码如下")
                .put("data",code);
    }

    @Override
    public RestResult VerifyInvitationCodeAndChangeRole(Integer userId, String invitationCode) {
        InvitationCode codePojo = invitationCodeMapper.selectByPrimaryKey(invitationCode);
        if (codePojo==null || codePojo.getStatusId().equals(1)) {
            return RestResult.failure("验证码错误或者验证码不存在或者验证码已经失效啦，再检查一次哦！");
        }

        User user = userMapper.selectByPrimaryKey(userId);
        if (user==null || user.getUserStatus().equals(0)) {
            RestResult.failure("用户不存在,或者用户不可用");
        }
        // 异步执行插入数据库操作
        UserServiceImpl bean = SpringUtil.getBean(UserServiceImpl.class);
        bean.changeUserRole(userId, invitationCode);

        return RestResult.success(user.getUserRealname() + "：成为了超级管理员");
    }

    @Async
    public void changeUserRole(Integer userId, String code) {
        // 改变用户的角色
        User user = new User();
        user.setRoleId(UniversityConstants.ADMIN_ROLE_ID);
        user.setUserId(userId);
        int row = userMapper.updateByPrimaryKeySelective(user);
        if (row < 1) {
            throw new RuntimeException("用户修改失败");
        }

        // 将邀请码状态设置为不可用
        InvitationCode invitationCode = new InvitationCode();
        invitationCode.setStatusId(1);
        invitationCode.setAdminCode(code);
        invitationCode.setUseUserId(userId);
        row = invitationCodeMapper.updateByPrimaryKeySelective(invitationCode);
        if (row < 1) {
            throw new RuntimeException("邀请码状态修改失败");
        }
    }

    @Async
    public void insertInvitationCodeDb(Integer userId, String code) {

        InvitationCode invitationCode = new InvitationCode();
        invitationCode.setAdminCode(code);
        invitationCode.setCreateUserId(userId);
        // 设置邀请码的状态为有效
        invitationCode.setStatusId(0);

        invitationCodeMapper.insert(invitationCode);
    }

    /**
     * 检查上传的文件是否是图片
     * @param multipartFile 文件
     * @return 是否是图片
     */
    private boolean checkIsImage(MultipartFile multipartFile) {

        // 原始文件名称
        String fileName = multipartFile.getOriginalFilename();

        // 解析到文件后缀，判断是否合法
        int index = fileName.lastIndexOf(".");
        String suffix = null;
        if (index == -1 || (suffix = fileName.substring(index + 1)).isEmpty()) {
            return false;
        }

        // 允许上传的文件后缀列表
        Set<String> allowSuffix = new HashSet<>(Arrays.asList("jpg", "jpeg", "png", "gif"));
        if (!allowSuffix.contains(suffix.toLowerCase())) {
            return false;
        }
        return true;
    }

    /**
     * 获得用户的头像文件名
     * @param userId 用户id
     * @return 用户头像文件名
     */
    private String getFileName(Integer userId) {

        UserImage imageName = userImageMapper.selectByPrimaryKey(userId);
        return imageName.getFileName();
    }
}
